/*
  This file is part of 'Trivial chess'.

  'Trivial chess' is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  'Trivial chess' is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with 'Trivial chess'.  If not, see <http://www.gnu.org/licenses/>.
*/

/* SVN FILE: $Id$ */
/**
 * @author         $Author$
 * @version        $Rev$
 * @lastrevision   $Date$
 * @filesource     $URL$
 */

//#define BOOST_TEST_MODULE Man
#include <boost/test/unit_test.hpp>
#include "../config.h"


BOOST_AUTO_TEST_SUITE( ManTest )

const Man MEN[] = {
		Man::WHITE_PAWN(),
		Man::BLACK_PAWN(),
		Man::WHITE_BISHOP(),
		Man::BLACK_BISHOP(),
		Man::WHITE_KNIGHT(),
		Man::BLACK_KNIGHT(),
		Man::WHITE_ROOK(),
		Man::BLACK_ROOK(),
		Man::WHITE_QUEEN(),
		Man::BLACK_QUEEN(),
		Man::WHITE_KING(),
		Man::BLACK_KING(),
		Man::NIL()
	};

const char* MEN_STR[] =
	{"P","p","B","b","N","n","R","r","Q","q","K","k","-"};

const int MEN_LENGTH = 13;

BOOST_AUTO_TEST_CASE( testPiece ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];
		BOOST_CHECK_EQUAL(man.piece().toInt(),(i / 2));
	}
}

BOOST_AUTO_TEST_CASE( testColor ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];
		BOOST_CHECK_EQUAL(man.color().toInt(),(i % 2));
	}
}

BOOST_AUTO_TEST_CASE( testSetPiece ) {
	Man man = Man::WHITE_PAWN();
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		man.setPiece( MEN[i].piece() );
		BOOST_CHECK_EQUAL(man.piece(), MEN[i].piece());
		BOOST_CHECK(man.color().isWhite());
	}
	man = Man::BLACK_PAWN();
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		man.setPiece( MEN[i].piece() );
		BOOST_CHECK_EQUAL(man.piece(), MEN[i].piece());
		BOOST_CHECK(man.color().isBlack());
	}
}

BOOST_AUTO_TEST_CASE( testSetColor ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];
		man.setColor( Color::WHITE() );
		BOOST_CHECK(man.color().isWhite());
		BOOST_CHECK_EQUAL(man.piece(), MEN[i].piece());
		man.setColor( Color::BLACK() );
		BOOST_CHECK(man.color().isBlack());
		BOOST_CHECK_EQUAL(man.piece(), MEN[i].piece());
	}
}


BOOST_AUTO_TEST_CASE( fromColorAndPiece ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Piece piece;
		piece.fromInt(i/2);
		Color color;
		color.fromInt(i%2);
		Man man;
		man.fromColorAndPiece(color, piece);
		BOOST_CHECK_EQUAL(man, MEN[i]);
	}
}

BOOST_AUTO_TEST_CASE( testMan_Color_Piece ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Piece piece;
		piece.fromInt(i/2);
		Color color;
		color.fromInt(i%2);
		Man man =  Man(color, piece);
		BOOST_CHECK_EQUAL(man, MEN[i]);
	}
}

BOOST_AUTO_TEST_CASE( testEqual ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];
		BOOST_CHECK_EQUAL(man, MEN[i]);
	}
}

BOOST_AUTO_TEST_CASE( testNotEqual ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man1 = MEN[i];
		for ( int j = 0; j < 7; ++j ) {
			Man man2 = MEN[j];
			if ( i != j )
				BOOST_CHECK_NE(man1, man2);
		}
	}
}

#define TEST_IS_MAN(name,num) \
	for ( int i = 0; i < MEN_LENGTH; ++i ) { \
		Man man = MEN[i]; \
		if ( num == i ) \
			BOOST_CHECK( man.is##name() ); \
		else \
			BOOST_CHECK( !man.is##name() ); \
	}

BOOST_AUTO_TEST_CASE( testIsWhitePawn ) {
	TEST_IS_MAN(WhitePawn,0);
}

BOOST_AUTO_TEST_CASE( testIsBlackPawn ) {
	TEST_IS_MAN(BlackPawn,1);
}

BOOST_AUTO_TEST_CASE( testIsWhiteBishop ) {
	TEST_IS_MAN(WhiteBishop,2);
}

BOOST_AUTO_TEST_CASE( testIsBlackBishop ) {
	TEST_IS_MAN(BlackBishop,3);
}

BOOST_AUTO_TEST_CASE( testIsWhiteKnight ) {
	TEST_IS_MAN(WhiteKnight,4);
}

BOOST_AUTO_TEST_CASE( testIsBlackKnight ) {
	TEST_IS_MAN(BlackKnight,5);
}

BOOST_AUTO_TEST_CASE( testIsWhiteRook ) {
	TEST_IS_MAN(WhiteRook,6);
}

BOOST_AUTO_TEST_CASE( testIsBlackRook ) {
	TEST_IS_MAN(BlackRook,7);
}

BOOST_AUTO_TEST_CASE( testIsWhiteQueen ) {
	TEST_IS_MAN(WhiteQueen,8);
}

BOOST_AUTO_TEST_CASE( testIsBlackQueen ) {
	TEST_IS_MAN(BlackQueen,9);
}

BOOST_AUTO_TEST_CASE( testIsWhiteKing ) {
	TEST_IS_MAN(WhiteKing,10);
}

BOOST_AUTO_TEST_CASE( testIsBlackKing ) {
	TEST_IS_MAN(BlackKing,11);
}

BOOST_AUTO_TEST_CASE( testIsNil ) {
	TEST_IS_MAN(Nil,12);
}

#undef TEST_IS_MAN

BOOST_AUTO_TEST_CASE( testMan_Int ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = Man(i);
		BOOST_CHECK_EQUAL(man, MEN[i]);
	}
}

BOOST_AUTO_TEST_CASE( testToInt ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];
		BOOST_CHECK_EQUAL(man.toInt(), i);
	}
}

BOOST_AUTO_TEST_CASE( testFromInt ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man;
		man.fromInt(i);
		BOOST_CHECK_EQUAL(man, MEN[i]);
	}
}

BOOST_AUTO_TEST_CASE( testInc ) {
	int i = 0;
	Man man = Man::BEGIN();
	while ( i < MEN_LENGTH - 1 ) {
		BOOST_CHECK_EQUAL(MEN[i], man);
		++man;
		++i;
	}
	BOOST_CHECK_EQUAL(man, Man::END());
}

BOOST_AUTO_TEST_CASE( testDec ) {
	int i = MEN_LENGTH - 2;
	Man man = Man::RBEGIN();
	while ( i >= 0 ) {
		BOOST_CHECK_EQUAL(MEN[i], man);
		--man;
		--i;
	}

	BOOST_CHECK_EQUAL(man, Man::REND());
}

BOOST_AUTO_TEST_CASE( toStrTest ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man = MEN[i];

		BOOST_CHECK_EQUAL(man.toStr(), MEN_STR[i]);
	}
}

BOOST_AUTO_TEST_CASE( fromStrTest ) {
	for ( int i = 0; i < MEN_LENGTH; ++i ) {
		Man man;
		man.fromStr(MEN_STR[i]);

		BOOST_CHECK_EQUAL(man.toInt(), MEN[i].toInt());
	}
}

#define TEST_IS_MAN(name) \
	for ( int i = 0; i < MEN_LENGTH; ++i ) { \
		Man man = MEN[i]; \
		BOOST_CHECK_EQUAL( man.is##name(), man.color().is##name() ); \
	}

BOOST_AUTO_TEST_CASE( testIsWhite ) {
	TEST_IS_MAN( White );
}

BOOST_AUTO_TEST_CASE( testIsBlack ) {
	TEST_IS_MAN( Black );
}

#undef TEST_IS_MAN

#define TEST_IS_MAN(name) \
	for ( int i = 0; i < MEN_LENGTH; ++i ) { \
		Man man = MEN[i]; \
		BOOST_CHECK_EQUAL( man.is##name(), man.piece().is##name() ); \
	}

BOOST_AUTO_TEST_CASE( testIsPawn ) {
	TEST_IS_MAN( Pawn );
}

BOOST_AUTO_TEST_CASE( testIsBishop ) {
	TEST_IS_MAN( Bishop );
}

BOOST_AUTO_TEST_CASE( testIsKnight ) {
	TEST_IS_MAN( Knight );
}

BOOST_AUTO_TEST_CASE( testIsRook ) {
	TEST_IS_MAN( Rook );
}

BOOST_AUTO_TEST_CASE( testIsQueen ) {
	TEST_IS_MAN( Queen );
}

BOOST_AUTO_TEST_CASE( testIsKing ) {
	TEST_IS_MAN( King );
}

BOOST_AUTO_TEST_CASE( testIsLeaper ) {
	TEST_IS_MAN( Leaper );
}

BOOST_AUTO_TEST_CASE( testIsSlider ) {
	TEST_IS_MAN( Slider );
}

BOOST_AUTO_TEST_CASE( testIsMinor ) {
	TEST_IS_MAN( Minor );
}

BOOST_AUTO_TEST_CASE( testIsMajor ) {
	TEST_IS_MAN( Major );
}

#undef TEST_IS_MAN


BOOST_AUTO_TEST_SUITE_END()
